#include <fstream>
#include <boost/filesystem/path.hpp>
#include <iostream>
#include <string>
#include <stdio.h>
#include <math.h>
#include <boost/lexical_cast.hpp>
#include "components/CmdLine/cmdargs.h"
#include <boost/regex.hpp>
//#include "components/greta/regexpr2.h"
#include "get_arg.h"
using std::string;
using std::ofstream;
using std::ifstream;
using std::cerr;
using std::cout;
using boost::lexical_cast;





//_______________________________________________________________________________________

//		GetArguments

//				from command line
//				Created [9/13/2001]

//_______________________________________________________________________________________
bool GetArguments(int argc, char* argv[], t_program_args& args)
{
	// optional help directive
	CmdArgUsage opt_help('h', "help", 	"display this message", &cout);

	// required options
	const unsigned REQUIRED = CmdArg::isREQ | CmdArg::isVALREQ;
	CmdArgStr opt_fasta	('f', "fasta_file", "<string>",
								"sequence database filename. E.g. /smthng/a.fasta",
								REQUIRED);
	CmdArgStr opt_db_origin	('n', "name_source", "<string>",
								"unique identifier with < 5 letters "
								"for this sequence database.  E.g. SWISS",
								REQUIRED);
	CmdArgStr opt_dbname('d', "dbname", "<string>",
								"PostgreSQL database name. ", REQUIRED);
	CmdArgStr opt_host	('h', "host", "<string>",
								"PostgreSQL database host computer address. ");
	CmdArgStr opt_user	('u', "user", "<string>",
								"PostgreSQL database user name. Defaults to 'postgres'.");
	CmdArgStr opt_password('p', "password", "<string>",
								"PostgreSQL database password.");
	CmdArgStr opt_login('l', "login", "<string>",
								"Other PostgreSQL login parameters in the form of "
								"keyword = value. E.g \"port=1234\"");
	CmdArgStr opt_regex	('r', "regex", "<string>",	
								"regular expression for extracting accession codes. "
								"E.g '[^|]+\\|([^|]+)\\|'");
	
	CmdArgStr opt_err_log ('e', "err_log", "<string>",
								"file for logging errors "
								"(defaults to STDERR).");
	CmdArgSet opt_index	('i', "indices",
								"do not rebuild indices when adding "
								"sequences/annotations.");
	CmdArgSet opt_vacuum('s', "stats",
								 "recalibrate database stats for (possibly) faster queries.");
	CmdArgSet opt_verbose('v', "verbose",
								"issue lots more messages.");
	CmdArgSet opt_leave_orphans('o', "orphans",
								"leave as orphans obsolete sequences without "
								"corresponding accessions.");
	
	//     CmdArgInt  count('c', "count", "number", "# of copies to print");
	CmdArgInt opt_default_taxid('t', "taxid", "<number>",
								"NCBI Taxonomical ID (overrides any taxa found on the "
								"accession line.");
	opt_default_taxid = -99999;

	string exe_file_name =  boost::filesystem::path(*argv).leaf();
	
	
		
		// construct command line
	CmdLine  cmdline(exe_file_name.c_str(),
							&opt_fasta,
							&opt_db_origin,
							&opt_dbname,
							&opt_host,
							&opt_user,
							&opt_password,
							&opt_login,
							&opt_regex,
							&opt_err_log,
							&opt_default_taxid,
							&opt_index,
							&opt_vacuum,
							&opt_leave_orphans,

							&opt_verbose,
							&opt_help,
							0);

	// parse command line
	CmdArgvIter  argv_iter(--argc, ++argv);
	cmdline.description( "This program synchronizes the Panda SQL Database with the "
							"specified sequence file."   );
	if (cmdline.parse(argv_iter))
		return false;

	// define verbose first before any error messages generated
	args.verbose	= opt_verbose;


	// make sure the error log file is valid
	string err_log		= opt_err_log.str();
	args.log_to_file = err_log.length();
	if (args.log_to_file)
	{
		args.f_err_log.open(err_log.c_str(), std::ios_base::out | std::ios_base::ate);
		if (!args.f_err_log.good())
		{
			cerr << "ERROR!! Could not open the error log file (" << err_log << ").\n";
			return(false);
		}
		args.f_err_log.setf(std::ios_base::unitbuf);
	}



	
	// get fasta file name
	args.fasta_path		= opt_fasta;
	args.fasta_name		= GetFilePart(args.fasta_path);


	// make sure regex is valid
	args.regex_str	= opt_regex;
	if (!args.regex_str.length())
		args.regex_str = "[^|]+\\|([^|]+)\\|";

	try
	{	
		boost::regex try_pattern(args.regex_str);
	}
	catch (boost::bad_expression&)
	{
		args.CERR().strm() <<
			"ERROR!! This regular expression is not valid: (" << args.regex_str <<").\n";
		return false;
	}
/* GRETA regex code
	try
	{	
		regex::rpattern try_pattern(args.regex_str);
	}
	catch (regex::bad_regexpr&)
	{
		args.CERR().strm() <<
			"ERROR!! This regular expression is not valid: (" << args.regex_str <<").\n";
		return false;
	}
*/
	// make sure the tag name is not too long
	args.db_origin		= opt_db_origin;
	if (args.db_origin.length() > 5 || !args.db_origin.length())
	{
		args.CERR().strm() <<  "Error!!\n\tA tag name for the database <" << args.db_origin <<
								">\n\tmust be specified with no more than 5 letters!\n";
		return false;
	}



	// initialize postgresql login
	args.db_login = "dbname=" +opt_dbname.str();
	
	string user		= opt_user;
	if (opt_user.str().length())
		args.db_login += " user=" + opt_user.str();
	else
		args.db_login += " user=postgres";
	
	if (opt_host.str().length())
		args.db_login += " host=" + opt_host.str();
	
	if (opt_password.str().length())
		args.db_login += " password=" + opt_password.str();

	if (opt_login.str().length())
		args.db_login += ' ' + opt_login.str();
	
	
	// misc options
	args.recreate_indices	= !opt_index;
	args.vacuum 			= opt_vacuum;
	args.orphans			= !opt_leave_orphans;
	
	// get default taxid as a string
	if (opt_default_taxid == -99999)
		args.default_taxid = "";
	else
		args.default_taxid = lexical_cast<string>(static_cast<int>(opt_default_taxid));

	return true;
}

